package org.zt.java.dal.datasource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.zt.java.dal.config.DalConfig;
import org.zt.java.dal.loadbalance.LoadBalanceType;
import org.zt.java.dal.loadbalance.SlaveLoadBalance;
import org.zt.java.dal.router.DataSourceRouter;


public class DynamicDataSource extends AbstractRoutingDataSource implements ApplicationContextAware {

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	public static final String MASTER_NAME = "master";
	public static final String SLAVE_PREFIX = "slave_";
	private ApplicationContext applicationContext;
	private DalConfig dalConfig;

	// 配置文件地址
	private String address;
	private LoadBalanceType slaveBalance = LoadBalanceType.ConsistentHash;// 默认hash

	// 数据源选择路由
	private DataSourceRouter dataSourceRouter = null;
	private SlaveLoadBalance slaveLoadBalanceBean = null;

	@Override
	protected Object determineCurrentLookupKey() {
		try {
			return dataSourceRouter.selectCurrentDataSourceKey();
		} catch (Exception ex) {
			logger.error("判断数据源出错，请检查。此异常发生后，数据源自动选择主数据源，不会对业务产生影响", ex);
		}

		return null;
	}

	/**
	 * 重载父类方法，方便自定义bean属性
	 */
	@Override
	public void afterPropertiesSet() {
		// 1.校验配置参数
		if (this.address == null) {
			throw new IllegalArgumentException("Property 'address' is required");
		}

		DynamicDataSourceHelper helper = new DynamicDataSourceHelper(this, applicationContext);
		helper.loadAndParseDalConfig();
		helper.addDataSourceBeanToSpringContainer();
		helper.initDynamicDataSource();

		super.afterPropertiesSet();
		logger.info("DynamicDataSource 已初始化完成");
	}

	public LoadBalanceType getSlaveBalance() {
		return slaveBalance;
	}

	public void setSlaveBalance(LoadBalanceType slaveBalance) {
		this.slaveBalance = slaveBalance;
	}

	public SlaveLoadBalance getSlaveLoadBalanceBean() {
		return slaveLoadBalanceBean;
	}

	public void setSlaveLoadBalanceBean(SlaveLoadBalance slaveLoadBalanceBean) {
		this.slaveLoadBalanceBean = slaveLoadBalanceBean;
	}

	public DataSourceRouter getDataSourceRouter() {
		return dataSourceRouter;
	}

	public void setDataSourceRouter(DataSourceRouter dataSourceRouter) {
		this.dataSourceRouter = dataSourceRouter;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public void setDalConfig(DalConfig dalConfig) {
		this.dalConfig = dalConfig;
	}

	public DalConfig getDalConfig() {
		return dalConfig;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}
